##
## Put form classes which are specific to the contacts app in this file.
##


## You need the following if this is ever being run as a script 
from django import newforms as forms

import os, sys  
sys.path.insert(0, "C:\Documents and Settings\wendy_admin\src\eclipse_workspace\djangodb\main")  
if not os.environ.has_key("DJANGO_SETTINGS_MODULE"):
    os.environ["DJANGO_SETTINGS_MODULE"]="wjContact.settings"
  
## Python and third-party imports  
import datetime

## Database Models
from wjContact.contacts.models import Phone
from wjContact.contacts.models import Contact, Recipient, Volunteer
from wjContact.contacts.models import Group

## Extensible Forms
## Core cbv field-related stuff
import wjContact.views.forms as wjCoreForms

## Fields and Widgets
from wjContact.views.fields import FieldList 
from wjContact.contacts.views.fields import PhoneField
from wjContact.contacts.views.widgets import PhoneWidget


##============================================================================##
## Multi-table forms
## -----------------
## All of the forms we define in this module  (Contact. Recipient, Volunteer) 
## are forms which send data to more than one table.
##
## There are basically two things you need to do to make a form which can save 
## data to more than one table.
##
## 1. Add all the fields from each of the tables to the form.
## 2. Over-ride the 'save()' method of the form so that it correctly saves the 
##    data from each of these fields into the right table. This requires some
##    care when there are foreign-key relations between the tables (which there
##    usually are). 
##
## For instance, to completely save a 'Contact' database entry,
## you need to first save the general contact details to the 'Contact' table
## (first_name, last_name, address, suburb, state, country, email, and 
## date_added). You do this by making a 'contact' object and calling save() on 
## it. Then you need to make one or more PhoneNumber entries in the PhoneNumber
## table, using the data entered in the phone number-related widgets. 
##
## To make a 'Recipient' database entry, you need to do all of the above, and 
## then correctly save the Recipient-Specific details (stay-with-linux, 
## has-used-computer-before, and so on). Finally you need to make some 
## Language entries and correctly join these to the Recipient.
##
## At the moment, the below is pretty messy - still just trying things out.
## Some obvious stuff that needs fixing (just the start of a long list!):
## ** re-do the RecipientForm class, so that there is not as much 
##    overlap with stuff that the ContactForm already does. [done - they now 
##    inherit the overlapping stuff from ContactForm, ie the fields that exist
##    on both. And they call the ContactForm save() method before doing their
##    own specific save() stuff.]
## ** redo addAllContactView, and the various 'handle' views to reduce overlap
## 
## 
## ===========================================================================##
class ContactForm(wjCoreForms.ExtensibleForm):
    """ """   
    
    first_name = wjCoreForms.forms.CharField(max_length=40, initial="New")
    last_name = wjCoreForms.forms.CharField(max_length=20, initial="Contact")
    address = wjCoreForms.forms.CharField(max_length=200, initial="17 Sunny Street")
    suburb = wjCoreForms.forms.CharField(max_length=40, initial="North Melbourne")
    state = wjCoreForms.forms.CharField(max_length=2, initial="Vi")
    country = wjCoreForms.forms.CharField(max_length=40, initial="Antarctica")
    email = wjCoreForms.forms.EmailField(initial="contact@place.org")
    date_added = wjCoreForms.forms.DateTimeField(initial=datetime.date.today())
   
    ## Fields to go into Phone table.
    # <wsl> Next lines - crufty. Remove later?
    PHONE_CHOICES = Phone.PHONE_CHOICES
    phones = FieldList(
        base_name='phone', 
        template_field=PhoneField(
                                widget=PhoneWidget(),
                                initial="new_entry#0411-222-333#mobile#",
                                 ), 
        fk_fieldname="contact", 
        model_class=Phone
        )

    def save(self):
        """ 
        Over-ride the save method to allow saving different fields to 
        different tables.
        """            
        ## First save contact-data into the Contact table  
        if self.stage_type == 'fresh_add' or self.stage_type == 'touched_add':
            contact = Contact(
                first_name=self.clean_data['first_name'],
                last_name=self.clean_data['last_name'],
                address=self.clean_data['address'],
                suburb=self.clean_data['suburb'], 
                state=self.clean_data['state'],
                country=self.clean_data['country'],
                email=self.clean_data['email'] ,
                date_added=self.clean_data['date_added'],
                )          
            contact.save()
                 
        elif self.stage_type == 'fresh_edit' or self.stage_type == 'touched_edit':             
            contact=self.main_object
            contact.first_name=self.clean_data['first_name']
            contact.last_name=self.clean_data['last_name']
            contact.address=self.clean_data['address']
            contact.suburb=self.clean_data['suburb'] 
            contact.state=self.clean_data['state']
            contact.country=self.clean_data['country']
            contact.email=self.clean_data['email'] 
            contact.date_added=self.clean_data['date_added']
            contact.save()
                           
        ## Now save repeating/multiple fields 
        ## <Wsl> FIXME: 
        self.main_object = contact    
        self.save_fieldlists()      
        ## Now that we've saved all the appropriate data, return the new 
        ## owner object  - descendant classes may need it when they are going 
        ## through their own save() procedure. 
        return contact
     
## ===========================================================================##               
class RecipientForm(ContactForm):
    """
    A form for displaying both contact fields and recipient fields with a 
    single 'submit' button.
    """
   
    ## We should already have all of the generic-contact fields since we
    ## will inherit them from ContactForm.   
    
    ## Make any last-minute alterations to the original Contact data here!
    ## In particular, we will re-define the 'initial' value for the last_name 
    ## field to be 'Recipient' rather than 'Contact'.
    
    last_name = wjCoreForms.forms.CharField(max_length=20, initial="Recipient") 

    ## The next fields are for details that relate specifically to 
    ## recipient-type contacts  - ie data which is to be stored in the 
    ## Recipient table.
    
    ## Grab in the list of concession types used as choices for this field
    ## by the Recipient form.
    CONCESSION_CHOICES = Recipient.CONCESSION_TYPES
    INTERNET_TYPES = Recipient.INTERNET_TYPES
    ## And here are the felds.
    concession_type = wjCoreForms.forms.ChoiceField(choices=CONCESSION_CHOICES, initial="other")
    concession_checked_by = wjCoreForms.forms.ModelChoiceField(Volunteer.objects.all(), initial=1)
    #referring_org = wjCoreForms.forms.ModelChoiceField(Group.objects.all())
    install_windows = wjCoreForms.forms.BooleanField(initial=False, required=False)
    stay_with_linux = wjCoreForms.forms.BooleanField(initial=True, required=False)  
    survey_contact = wjCoreForms.forms.BooleanField(initial=True, required=False)  
    have_not_used_a_computer = wjCoreForms.forms.BooleanField(initial=False, required=False)
    can_type_documents = wjCoreForms.forms.BooleanField(initial=True, required=False)
    can_use_keyboard_and_mouse = wjCoreForms.forms.BooleanField(initial=True, required=False)
    can_use_email = wjCoreForms.forms.BooleanField(initial=True, required=False)
    can_use_internet = wjCoreForms.forms.BooleanField(initial=True, required=False)
    has_attended_training = wjCoreForms.forms.BooleanField(initial=False, required=False)
    internet_type = wjCoreForms.forms.ChoiceField(choices=INTERNET_TYPES, initial="none")
    
    def save(self):
        """
        Over-ride our save method so that we can save fields to more than
        one table.
        """    
        ## We need to save stuff into two different database tables
        ## here. 
        ## First we call the 'save()' method we have inherited from ContactForm. 
        ## This will correctly save all the data which should go into the 
        ## Contact table.
        ## Then we deal with saving the extra data which should go into the
        ## Recipient table.
        related_contact = ContactForm.save(self)
        # Now save the recipient-specific details into the recipient table,
        # and set the 'contact' to be the contact we just created.
        if self.stage_type == 'fresh_add' or self.stage_type == 'touched_add':      
            recipient = Recipient(contact=related_contact,
                concession_type = self.clean_data['concession_type'],
                concession_checked_by = self.clean_data['concession_checked_by'],
                #referring_org = self.clean_data['referring_org'],
                install_windows = self.clean_data['install_windows'],
                stay_with_linux = self.clean_data['stay_with_linux'],
                survey_contact = self.clean_data['survey_contact'],
                have_not_used_a_computer = self.clean_data['have_not_used_a_computer'],
                can_type_documents = self.clean_data['can_type_documents'],
                can_use_keyboard_and_mouse = self.clean_data['can_use_keyboard_and_mouse'],
                can_use_email = self.clean_data['can_use_email'],
                can_use_internet = self.clean_data['can_use_internet'],
                has_attended_training = self.clean_data['has_attended_training'],
                internet_type = self.clean_data['internet_type'],)
            recipient.save()
            
                 
        elif self.stage_type == 'fresh_edit' or self.stage_type == 'touched_edit':             
            recipient=self.main_object
            recipient.contact=related_contact,
            recipient.concession_type = self.clean_data['concession_type']
            recipient.concession_checked_by = self.clean_data['concession_checked_by']
            #recipient.referring_org = self.clean_data['referring_org']
            recipient.install_windows = self.clean_data['install_windows']
            recipient.stay_with_linux = self.clean_data['stay_with_linux']
            recipient.survey_contact = self.clean_data['survey_contact']
            recipient.have_not_used_a_computer = self.clean_data['have_not_used_a_computer']
            recipient.can_type_documents = self.clean_data['can_type_documents']
            recipient.can_use_keyboard_and_mouse = self.clean_data['can_use_keyboard_and_mouse']
            recipient.can_use_email = self.clean_data['can_use_email']
            recipient.can_use_internet = self.clean_data['can_use_internet']
            recipient.has_attended_training = self.clean_data['has_attended_training']
            recipient.internet_type = self.clean_data['internet_type']
            recipient.save()
                                 
        ## Now save repeating/multiple fields 
        ## <Wsl> FIXME 
        ## I think that self.main_object should always be contact, not recipient 
        ## etc. See ie save_fieldlists method for why!
        self.main_object = recipient    
        self.save_fieldlists()      
        ## Now that we've saved all the appropriate data, return the new 
        ## recipient object  - descendant classes may need it when they are going 
        ## through their own save() procedure. 
        return recipient
     
##============================================================================##   
class VolunteerForm(ContactForm):
    """ """   
      
    ## Make any last-minute alterations to the original Contact data here!
    ## In particular, we will re-define the 'initial' value for the last_name 
    ## field to be 'Volunteer' rather than 'Contact'.
    last_name = wjCoreForms.forms.CharField(max_length=20, initial="Volunteer") 
      
    ## And now add the fields specific to Volunteers  
    hours = wjCoreForms.forms.ChoiceField(choices=Volunteer.HOURS_CHOICES)
    interests = wjCoreForms.forms.ChoiceField(choices=Volunteer.INTERESTS)
    
    def save(self):
        """ 
        Over-ride the save method to allow saving different fields to 
        different tables.
        """            
        ## First save contact-data into the Contact table 
        related_contact = ContactForm.save(self) 
        if self.stage_type == 'fresh_add' or self.stage_type == 'touched_add':
            ## We need to save stuff into two different database tables
            ## here. 
            ## First we call the 'save()' method we have inherited from 
            ## ContactForm. 
            ## This will correctly save all the data which should go into the 
            ## Contact table.
            ## Then we deal with saving the extra data which should go into the
            ## Volunteer table.
            
            ## Now save the volunteer-specific details into the recipient table,
            ## and set the 'contact' to be the contact we just created. 
            volunteer = Volunteer(
                 contact = related_contact,
                 hours = self.clean_data['hours'],
                 interests = self.clean_data['interests']   
                 )          
            volunteer.save()
                 
        elif self.stage_type == 'fresh_edit' or self.stage_type == 'touched_edit':             
            volunteer=self.main_object
            volunteer.contact=related_contact,
            volunteer.hours = self.clean_data['hours'],
            volunteer.interests = self.clean_data['interests']   
            volunteer.save()
                        
        ## Now save repeating/multiple fields 
        ## <Wsl> FIXME:
        self.main_object = volunteer  
        self.save_fieldlists()      
        ## Now that we've saved all the appropriate data, return the new 
        ## object  - descendant classes may need it when they are going 
        ## through their own save() procedure. 
        return volunteer
           
class SearchForm(forms.Form):
	query = forms.CharField(
			label = "Enter name/suburb to search for:",
			widget = forms.TextInput(attrs={"size":32})
			)
